package com.inetools.gwetons.client.cssStyleChangerBySelector;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.inetools.gwetons.client.logging.JsniLogUtilAdapterTemplate;
import com.inetools.gwetons.shared.logging.LogUtil;

/**
 * CssStyleChangerDataUnit class represents each element of styleChangerDataArray JavaScript object
 * @author ay
 */
class CssStyleChangerDataUnit extends JsniLogUtilAdapterTemplate {
	@Override
	protected String getNameForLogging() {
		return this.getClass().getName();
	}

	final JavaScriptObject styleChangerDataUnit;
	
	public CssStyleChangerDataUnit( JavaScriptObject styleChangerDataUnit) {
		this.styleChangerDataUnit = styleChangerDataUnit;
	}
	
	native Boolean getBooleanImpl( String name) throws JavaScriptException /*-{
		// Preparations for logging ---------------------------------------------------------------
		var methodName = "getBooleanImpl JSNI";
		var thisJsniLogUtil 
		= this.@com.inetools.gwetons.client.cssStyleChangerBySelector.CssStyleChangerDataUnit::getJsniLogUtil()();
		var jsniLogEntering
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getEnteringFunction()();
		var jsniLogging
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getLogFunction()();
		var jsniLogResult
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getExitingWithResultFunction()();
		// ----------------------------------------------------------------------------------------
		
		jsniLogEntering( methodName, [ "name(=" + String( name) + ")"]);
			
		if ( typeof( name) != "string") {
			jsniLogging(
				@java.util.logging.Level::WARNING, 
				"Type of name input (=" + String( name) + ") is not string: "
				+ typeof( name)
				);
			jsniLogResult( methodName, null);
			return null;
		}
		
		var styleChangerDataUnit 
		= this.@com.inetools.gwetons.client.cssStyleChangerBySelector.CssStyleChangerDataUnit::styleChangerDataUnit;
		
		var propertyType = typeof( styleChangerDataUnit[ name]);
		if ( propertyType != 'boolean') {
			jsniLogging( 
				@java.util.logging.Level::FINEST, 
				"Value of " + name + "property is not boolean type: " + propertyType
				);
			jsniLogResult( methodName, null);
			return null;
		}
		
		jsniLogResult( methodName, styleChangerDataUnit[ name]);
		return @java.lang.Boolean::valueOf(Z)( styleChangerDataUnit[ name]);
	}-*/;
	
	Boolean getBoolean( JsDataPropertyIdentification jsDataPropertyIdentification) {
		String methodName = "getBoolean";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( methodName, new Object[]{ jsDataPropertyIdentification});
		
		if ( jsDataPropertyIdentification == null) {
			throw new IllegalArgumentException( "null value as propertyName input is not allowed.");
		}
		
		boolean isBooleanType = false;
			for( Class<?> typeObj : jsDataPropertyIdentification.getTypes()) {
				if ( typeObj.equals( Boolean.class)) {
					isBooleanType = true;
					break; // for
				}
			} // for
			if ( !isBooleanType) {
				throw new IllegalArgumentException( 
						"propertyName input " + jsDataPropertyIdentification.toString() + "is not boolean type.");
			}
		
		Boolean booleanObj = null;
			try {
				booleanObj = getBooleanImpl( jsDataPropertyIdentification.getJsPropertyName());
			}
			catch( Exception exception) { // Do nothing
				logUtil.log( 
						Level.WARNING, 
						"Value of " + jsDataPropertyIdentification.getJsPropertyName() 
						+ " property is not boolean type.", 
						exception
						);
			}
			
		logUtil.exiting( methodName, booleanObj);
		return booleanObj;
	} // protected final Boolean getBoolean( String propertyName)
	
	// About repeat property ----------------------------------------------------------------------
	Boolean repeatableObj = null;
		public boolean isRepeatable() {
			String methodName = "isRepeatable";
			LogUtil logUtil = getLogUtil();
			logUtil.entering( methodName, null);
			
			if ( repeatableObj != null) {
				logUtil.exiting( methodName, repeatableObj.booleanValue());
				return repeatableObj.booleanValue();
			}
			
			repeatableObj = getBoolean( JsDataPropertyIdentification.Repeatable);
				if ( repeatableObj == null) {
					repeatableObj = new Boolean( "false");
					logUtil.log( 
							Level.INFO, 
							"Set value of " + JsDataPropertyIdentification.Repeatable.toString() + "property to " 
							+ "false because of failure in reading it."
							);
				}
				
			logUtil.exiting( methodName, repeatableObj.booleanValue());
			return repeatableObj.booleanValue();
		}
	// --------------------------------------------------------------------------------------------
	
	// About sequence property --------------------------------------------------------------------
	Boolean sequenceObj = null;
		public boolean isSequence() {
			String methodName = "isSequence";
			LogUtil logUtil = getLogUtil();
			logUtil.entering( methodName, null);
			
			if ( sequenceObj != null) {
				logUtil.exiting( methodName, sequenceObj.booleanValue());
				return sequenceObj.booleanValue();
			}
			
			sequenceObj = getBoolean( JsDataPropertyIdentification.Sequence);
				if ( sequenceObj == null) {
					sequenceObj = new Boolean( "false");
					logUtil.log( 
							Level.INFO, 
							"Set value of " + JsDataPropertyIdentification.Sequence.toString() + "property to " 
							+ "false because of failure in reading it."
							);
				}
			
			logUtil.exiting( methodName, sequenceObj.booleanValue());
			return sequenceObj.booleanValue();
		}
	// --------------------------------------------------------------------------------------------
		
	native JsArray<JavaScriptObject> getDataUnitByStyleSelectorArray() throws JavaScriptException /*-{
		// Just logging preparation ---------------------------------------------------------------
		var methodName = "getDataUnitByStyleSelectorArray";
		var thisJsniLogUtil 
		= this.@com.inetools.gwetons.client.cssStyleChangerBySelector.CssStyleChangerDataUnit::getJsniLogUtil()();
		var jsniLogEntering
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getEnteringFunction()();
		var jsniLogging
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getLogFunction()();
		var jsniLogResult
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getExitingWithResultFunction()();
		// ----------------------------------------------------------------------------------------
		
		jsniLogEntering( methodName, null);
			
		var styleChangerDataUnit 
		= this.@com.inetools.gwetons.client.cssStyleChangerBySelector.CssStyleChangerDataUnit::styleChangerDataUnit;
		
		var selectorUnitArrayId 
		= @com.inetools.gwetons.client.cssStyleChangerBySelector.JsDataPropertyIdentification::SelectorUnitArray;
		var propertyName
		= selectorUnitArrayId.@com.inetools.gwetons.client.cssStyleChangerBySelector.JsDataPropertyIdentification::getJsPropertyName()();
		
		var propertyType = typeof( styleChangerDataUnit[ propertyName]);
			if ( propertyType != "object") {
				jsniLogging( 
					@java.util.logging.Level::WARNING, 
					"Value of selectorUnitArray property is not object type: " + propertyType
					);
				jsniLogResult( methodName, null);
				return null;
			}
		var selectorUnitArray = styleChangerDataUnit[ propertyName];
			if ( selectorUnitArray == null) {
				jsniLogging( 
					@java.util.logging.Level::INFO, 
					"Value of selectorUnitArray property is null"
					);
				jsniLogResult( methodName, null);
				return null;
			}
			if ( selectorUnitArray[ "constructor"] !== Array) {
				jsniLogging( 
					@java.util.logging.Level::WARNING, 
					"Value of selectorUnitArray property is not array type"
					);
				jsniLogResult( methodName, null);
				return null;
			}
			
		jsniLogResult( methodName, selectorUnitArray);
		return selectorUnitArray;
	}-*/;
	
	List<DataUnitByStyleSelector> dataUnitByStyleSelectorList = null;
		List<DataUnitByStyleSelector> getDataUnitByStyleSelectorList() {
			String methodName = "getDataUnitByStyleSelectorList";
			LogUtil logUtil = getLogUtil();
			logUtil.entering( methodName, null);
			
			if ( dataUnitByStyleSelectorList != null) {
				logUtil.exiting( methodName, dataUnitByStyleSelectorList);
				return dataUnitByStyleSelectorList;
			}
			
			JsArray<JavaScriptObject> dataUnitByStyleSelectorArray = getDataUnitByStyleSelectorArray();
				if ( dataUnitByStyleSelectorArray == null) {
					logUtil.exiting( methodName, null);
					return null;
				}
			
			List<DataUnitByStyleSelector> list = new ArrayList<DataUnitByStyleSelector>();
				for( int index = 0; index < dataUnitByStyleSelectorArray.length(); index++) {
					JavaScriptObject dataUnitByStyleSelectorObj = dataUnitByStyleSelectorArray.get( index);
					DataUnitByStyleSelector dataUnitByStyleSelector 
					= new DataUnitByStyleSelector( dataUnitByStyleSelectorObj);
					list.add( dataUnitByStyleSelector);
				} // for
				if ( list.size() < 1) {
					logUtil.log( 
							Level.INFO, 
							"Found no element in selectorUnitArray property"
							);
					logUtil.exiting( methodName, null);
					return null;
				}
			
			if ( dataUnitByStyleSelectorList == null) {
				dataUnitByStyleSelectorList = list;
			}
				
			logUtil.exiting( methodName, dataUnitByStyleSelectorList);
			return dataUnitByStyleSelectorList;
		}
}
